package com.taxinfo.utils;

import java.io.*;
import java.security.*;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.time.Instant;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.temporal.ChronoUnit;
import java.util.Base64;
import java.util.Date;

public class ToolManager {

    // 生成公私钥对
    public static void generateKeyPair() throws NoSuchAlgorithmException, IOException {
        KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA");
        keyPairGenerator.initialize(2048);
        KeyPair keyPair = keyPairGenerator.generateKeyPair();

        PrivateKey privateKey = keyPair.getPrivate();
        PublicKey publicKey = keyPair.getPublic();

        try (FileOutputStream privateKeyOut = new FileOutputStream("prikey.der");
             FileOutputStream publicKeyOut = new FileOutputStream("pubkey.der")) {
            privateKeyOut.write(privateKey.getEncoded());
            publicKeyOut.write(publicKey.getEncoded());
        }
    }

    // 生成 License 文件
    public static void generateLicense(Date validFrom, Date validTo) throws Exception {
        PrivateKey privateKey = loadPrivateKey();
        String licenseData = validFrom.getTime() + "," + validTo.getTime();
        String signature = signData(licenseData, privateKey);

        Tools license = new Tools(validFrom, validTo, signature);
        try (ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("license.dat"))) {
            oos.writeObject(license);
        }
    }

    public static String getValidTime()  throws Exception {
        String validDate= "";
        PublicKey publicKey = loadPublicKey();
        try (ObjectInputStream ois = new ObjectInputStream(new FileInputStream("license.dat"))) {
            Tools license = (Tools) ois.readObject();
            long startTime =  license.getValidFrom().getTime();
            long endTime =  license.getValidTo().getTime();
            Instant sinstant = Instant.ofEpochMilli(startTime);
            Instant einstant = Instant.ofEpochMilli(endTime);
            LocalDateTime sdt = LocalDateTime.ofInstant(sinstant, ZoneId.systemDefault());
            LocalDateTime edt = LocalDateTime.ofInstant(einstant, ZoneId.systemDefault());
            // 计算两个日期之间相差的天数
            long daysDifference = ChronoUnit.DAYS.between(sdt, edt);
            if(daysDifference<15){
                validDate = "软件使用还剩"+daysDifference+"天,为不影响软件使用，请提前联系管理员进行续费。";
            }
//            DateTimeFormatter dtf = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
//            String startDate = sdt.format(dtf);
//            String endDate = edt.format(dtf);
        }
        return validDate;
    }

    // 验证 License
    public static boolean validateLicense() throws Exception {
        PublicKey publicKey = loadPublicKey();
        try (ObjectInputStream ois = new ObjectInputStream(new FileInputStream("license.dat"))) {
            Tools license = (Tools) ois.readObject();
            String licenseData = license.getValidFrom().getTime() + "," + license.getValidTo().getTime();
            boolean isSignatureValid = verifySignature(licenseData, license.getSignature(), publicKey);
            return isSignatureValid && license.isValid();
        }
    }

    // 加载私钥
    private static PrivateKey loadPrivateKey() throws Exception {
        try (FileInputStream fis = new FileInputStream("prikey.der")) {
            byte[] keyBytes = new byte[fis.available()];
            fis.read(keyBytes);
            PKCS8EncodedKeySpec spec = new PKCS8EncodedKeySpec(keyBytes);
            KeyFactory keyFactory = KeyFactory.getInstance("RSA");
            return keyFactory.generatePrivate(spec);
        }
    }

    // 加载公钥
    private static PublicKey loadPublicKey() throws Exception {
        try (FileInputStream fis = new FileInputStream("pubkey.der")) {
            byte[] keyBytes = new byte[fis.available()];
            fis.read(keyBytes);
            X509EncodedKeySpec spec = new X509EncodedKeySpec(keyBytes);
            KeyFactory keyFactory = KeyFactory.getInstance("RSA");
            return keyFactory.generatePublic(spec);
        }
    }

    // 签名数据
    private static String signData(String data, PrivateKey privateKey) throws Exception {
        Signature signature = Signature.getInstance("SHA256withRSA");
        signature.initSign(privateKey);
        signature.update(data.getBytes());
        byte[] signBytes = signature.sign();
        return Base64.getEncoder().encodeToString(signBytes);
    }

    // 验证签名
    private static boolean verifySignature(String data, String signatureStr, PublicKey publicKey) throws Exception {
        Signature signature = Signature.getInstance("SHA256withRSA");
        signature.initVerify(publicKey);
        signature.update(data.getBytes());
        byte[] signatureBytes = Base64.getDecoder().decode(signatureStr);
        return signature.verify(signatureBytes);
    }
}
